package com.study.controller;

import com.study.limiter.JedisLuaTimeWindowLimiter;
import com.study.locks.redis.JedisPoolUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 秒杀限流
 *
 * @author: chenhs
 * @date: Created in 15:48 2019/12/19
 **/
@RestController
@RequestMapping("/order")
public class OrderController {

    /**
     * 抢购数量5
     */
    static long limit = 5;

    //线程不安全
    //private long count = 0;
    /**
     * 使用原子类（单机时）-- 底层实现原理CAS
     */
    private AtomicLong count = new AtomicLong(0);

    @GetMapping("add")
    public String doOrder(String name) {
        long c = count.incrementAndGet();
        if (c > limit) {
            return "秒杀结束，谢谢参与！count = " + c;
        }
        return "恭喜，秒杀成功！count = " + c;
    }


    /**
     * 访问测试
     * 地址1：http://localhost:8080/order/add2?name=mike666
     * 地址2：http://localhost:8082/order/add2?name=mike666
     *
     * 支持多机
     *
     * @param name
     * @return
     */
    @GetMapping("add2")
    public String doOrder2(String name) {
        Jedis jedis = null;
        try {
            jedis = JedisPoolUtil.getJedis();
            long c = jedis.incr(name);
            if (c > limit) {
                return "秒杀结束，谢谢参与！count = " + c;
            }
            return "恭喜，秒杀成功！count = " + c;
        } finally {
            JedisPoolUtil.closeJedis(jedis);
        }
    }

    /**
     * 时间窗 - redis实现
     *
     * 访问测试：
     * 地址1：http://localhost:8080/order/query?name=xxx
     * 地址2：http://localhost:8082/order/query?name=xxx
     *
     * @param name
     * @return
     */
    @GetMapping("query")
    public String doQuery(String name) {
        Jedis jedis = null;
        try {
            jedis = JedisPoolUtil.getJedis();
            long c = jedis.incr(name);
            if (c > limit) {
                return System.currentTimeMillis() / 1000 + "秒杀结束，谢谢参与！count = " + c;
            } else {
                if (c == 1) {
                    // 设置过期时间
                    jedis.expire(name, 1);
                }
            }
            return System.currentTimeMillis() / 1000 + "恭喜，秒杀成功！count = " + c;
        } finally {
            JedisPoolUtil.closeJedis(jedis);
        }
    }


    JedisLuaTimeWindowLimiter jtwl = new JedisLuaTimeWindowLimiter("Mike-666999", "5", "5", "lua/timeWindowLimit.lua");

    /**
     * 时间窗 - lua脚本实现
     *
     * 奇怪，为什么过完一个时间窗之后，就请求没响应了呢？什么原因？ -> redis连接池没关闭，连接数耗尽
     *
     * 访问测试：
     * 地址1：http://localhost:8080/order/query2
     * 地址2：http://localhost:8082/order/query2
     *
     * @param name
     * @return
     */
    @GetMapping("query2")
    public String doQuery2(String name) {
        if (!jtwl.acqure()) {
            return System.currentTimeMillis() / 1000 + "秒杀结束，谢谢参与！";
        }
        return System.currentTimeMillis() / 1000 + "恭喜，秒杀成功！";
    }




}
